#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import json
from datetime import datetime

import rclpy
from rclpy.node import Node
from std_msgs.msg import String


class CombineNetworkNode(Node):
    """
    订阅：
      - /network/iface_ip        （std_msgs/String，JSON 对象或数组）
      - /network/devices_status  （std_msgs/String，JSON 数组）
    发布：
      - /network/overview        （std_msgs/String，JSON 数组）
        形式：
        [
          { "name": "...", "ip": "...", "online": true, ... },
          ...
        ]
    """

    def __init__(self):
        super().__init__('combine_network_node')

        # 参数（可通过 --ros-args 覆盖）
        self.declare_parameter('iface_topic', 'network/iface_ip')
        self.declare_parameter('devices_topic', 'network/devices_status')
        self.declare_parameter('overview_topic', 'network/overview')
        self.declare_parameter('period_sec', 1.0)
        self.declare_parameter('pretty', True)

        self.iface_topic = self.get_parameter('iface_topic').value
        self.devices_topic = self.get_parameter('devices_topic').value
        self.overview_topic = self.get_parameter('overview_topic').value
        self.period_sec = float(self.get_parameter('period_sec').value)
        self.pretty = bool(self.get_parameter('pretty').value)

        # 最新缓存
        self._latest_iface = []     # 🔹改为 list
        self._latest_devices = []   # list

        # 订阅
        self.create_subscription(String, self.iface_topic, self._on_iface, 10)
        self.create_subscription(String, self.devices_topic, self._on_devices, 10)

        # 发布
        self.pub = self.create_publisher(String, self.overview_topic, 10)

        # 定时发布
        self.create_timer(self.period_sec, self._tick)

        self.get_logger().info(
            f"CombineNetworkNode 启动：iface={self.iface_topic}  devices={self.devices_topic}  "
            f"-> overview={self.overview_topic}  period={self.period_sec}s"
        )

    # 🔹 iface 现在可能是对象或数组，两种都支持
    def _on_iface(self, msg: String):
        try:
            data = json.loads(msg.data)
            if isinstance(data, dict):
                self._latest_iface = [data]
            elif isinstance(data, list):
                self._latest_iface = data
            else:
                self.get_logger().warn("iface_ip 不是 JSON 对象或数组，已忽略")
        except Exception as e:
            self.get_logger().warn(f"iface_ip 解析失败：{e}")

    def _on_devices(self, msg: String):
        try:
            data = json.loads(msg.data)
            if isinstance(data, list):
                self._latest_devices = data
            else:
                self.get_logger().warn("devices_status 不是 JSON 数组，已忽略")
        except Exception as e:
            self.get_logger().warn(f"devices_status 解析失败：{e}")

    # 周期合并并发布
    def _tick(self):
        # 1. 合并最新缓存，_latest_iface 和 _latest_devices 都是 list[dict]
        merged_raw = []

        if self._latest_iface:
            merged_raw.extend(self._latest_iface)

        if self._latest_devices:
            merged_raw.extend(self._latest_devices)

        if not merged_raw:
            return  # 没数据就不发

        # 2. 按设备名聚合，保留每个 name 的最新信息
        #    如果同一个设备出现多条记录，我们用最后一条覆盖前一条
        #    （你之前的语义是 "按 name 保留最新"）
        dedup = {}
        for item in merged_raw:
            if not isinstance(item, dict):
                continue  # 安全保护：跳过脏数据
            name = item.get("name")
            if not name:
                continue     # 没有 name 的设备我们不认
            dedup[name] = item

        # 3. 去重后的设备列表
        devices_list = list(dedup.values())

        # 4. 包装成你想要的最终结构：{"ip": [ {...}, {...} ]}
        final_payload = {
            "ip": devices_list
        }

        # 5. 转成字符串并发布
        out = String()
        if self.pretty:
            out.data = json.dumps(final_payload, ensure_ascii=False, indent=2)
        else:
            out.data = json.dumps(final_payload, ensure_ascii=False, separators=(",", ":"))
        self.pub.publish(out)

        # 调试输出
        # self.get_logger().info(f"发布网络概览数组，共 {len(merged)} 个设备")



def main():
    rclpy.init()
    node = CombineNetworkNode()
    try:
        rclpy.spin(node)
    finally:
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()
